#coding:utf8
from config import *
from config_mouse_start import *
import win32gui
import win32con
to_lock = threading.Lock()

def ig_left():
    if not cfg.w2showing and cfg.min_ge==0 and not cfg.is_pressed:
        return True
    return False

def is_acc_up():
    return cfg.acc_speed==g_mouse_speed[2]
def kuai_into_2():
    jump_state_chg(0)
    cfg.jump_kuai=2
    cfg.an_mode=True
    set_acc()
mosue_speed_q = deque()
def is_system_move(ct):
    if not (ct-cfg.right_mouse_time<0.1 and  ct-cfg.left_mouse_time<left_mouse_delay) :
        return False
    if not (cfg.jump_state==0 and cfg.jump_kuai==0):
        return False
    if cfg.has_gap:
        return False
    if is_acc_up() and cfg.ori_kuai==1:
        return False
    dd = abs(cfg.track_dx[0]+cfg.track_dx[2]) +abs(cfg.track_dx[1]+cfg.track_dx[3])
    if dd <shuangJumpLimit and cfg.track_dx_abs<shuangJumpLimit_abs and not \
        (cfg.slow_start_time!=0 and ct-cfg.slow_start_time>0.5) and not \
            cfg.track_has_wheel:
        return True
    if cfg.track_has_wheel and cfg.slow_start_time!=0:
        return False
    if cfg.slow_start_time!=0 and ct-cfg.slow_start_time>0.15 and cfg.max_speed>mouse_speed_gap[1]:
        return False
    if cfg.slow_start_time!=0 and ct-cfg.slow_start_time>0.25:
        return False
    return True

def cal_mouse_speed(x,y,t):    
    mouse_sqeed_intervalx = 0.05
    mosue_speed_q.append((x,y,t))
    while len(mosue_speed_q)>0:
        if t-mosue_speed_q[0][-1]>mouse_sqeed_intervalx:
            mosue_speed_q.popleft()
            continue
        else:
            break
    if len(mosue_speed_q)<2:
        cfg.mouse_speed=0
        return
   
    to = 0
    tx = 0
    ty = 0
    
    for i in mosue_speed_q:
        tx += abs(i[0])
        ty += abs(i[1])
    to = math.sqrt(tx*tx+ty*ty)
    cfg.mouse_speed=to/mouse_sqeed_intervalx    
    
def acc_total():
    set_kuai(0)
    cfg.can_set_acc=True
    set_acc()
    cfg.acc_no_reset=True

def acc_up_clear():
        cfg.acc_speed_co == 0
        cfg.ori_kuai=0
def acc_up():
    if cfg.g_is_acc and cfg.acc_speed!=g_mouse_speed[2]:
        win32gui.SystemParametersInfo(win32con.SPI_SETMOUSESPEED,g_mouse_speed[2],0)    
        cfg.acc_speed = g_mouse_speed[2]
        acc_up_clear()
        print('acc up',time.time(),cfg.acc_add)
        
def acc_down(force=False):
    if cfg.g_is_acc and cfg.acc_speed!=g_mouse_speed[0]:
        cfg.acc_speed_co += 1
        if cfg.acc_speed_co%2!=0 and not force:
            return
        win32gui.SystemParametersInfo(win32con.SPI_SETMOUSESPEED,g_mouse_speed[0],0)    
        cfg.acc_speed = g_mouse_speed[0]   
        print('acc down',time.time(),cfg.acc_add)

def set_acc():
    if cfg.g_is_acc==1:
        return
    cfg.g_is_acc=1
    win32gui.SystemParametersInfo(win32con.SPI_SETMOUSE,(6,10,1))    
    win32gui.SystemParametersInfo(win32con.SPI_SETMOUSESPEED,g_mouse_speed[0],0)    
    cfg.acc_speed = g_mouse_speed[0]
    print('set acc',time.time(),cfg.acc_add)
def change_left_jump():
    cfg.left_jump = not cfg.left_jump
    cfg.jump_add=0
    cfg.left_jump_can_chg = True
    if not cfg.left_jump:
        cfg.left_jump_can_chg = False

def set_no_acc(cpos,ct):
    if cfg.g_is_acc==0:
        return
    if cfg.jump_state==0 and ct-cfg.left_mouse_time>0.2:
        dd = cal_dis(cfg.track_start_pos,cpos)
        if dd<no_set_acc_gap:
            return
    cfg.g_is_acc=0
    win32gui.SystemParametersInfo(win32con.SPI_SETMOUSE,(0,0,0))   
    win32gui.SystemParametersInfo(win32con.SPI_SETMOUSESPEED,g_mouse_speed[1],0)    
    print('set no acc',time.time(),cfg.acc_add)

def enter_force():
    clear(True)
    cfg.show_one_on=True
    cfg.force_show = True
    
def enter_ge_mode(a):
    cfg.eg_from_mid=False
    enter_force()
    ge_add_xing(0)
    ge_set(a)

def jump_state_switch():
    if cfg.jump_state==0:
        jump_state_chg(1)
        return
    jump_state_chg(0)
    return

def jump_state_sup2():
    if is_jump_base() or not  cfg.mouse_tip_no_show:
        return False
    
    if time.time()-cfg.left_mouse_time<left_mouse_delay or cfg.jump_state!=0  or cfg.jump_kuai!=0 or \
        cfg.middle_pressed or (cfg.x2_pressed and cfg.x2_type==0) or cfg.need_jump or \
            (is_acc_up() and cfg.ori_kuai==1) :
        return True
    return False

def is_qu():
    if cfg.jump_state==1 and not cfg.x2_mode:
        if (cfg.jump_from_click or not cfg.can_break):
            return False
        return True
    return False
def jump_state_chg(a):    
    if a==0:
        cfg.last_move_is_right_solo=False
    cfg.keep_qu=False
    if a==0:
        cfg.left_jump=False
        cfg.jump_add=0
    if cfg.jump_state==0 and a==1:
        cfg.left_jump_can_chg = True
    set_kuai(0)
    cfg.man_has_left=False
    cfg.man_has_left=False
    cfg.first_left_time=0
    cfg.first_right_time=0
    cfg.jump_from_click = True
    cfg.can_break=False
    cfg.jump_to = 0
    cfg.jump_dx = [0,0]
    cfg.jump_state = a
    if a==1:
        cfg.jump_left_pos=get_cur_pos()
    else:
        cfg.jump_left_pos=[0,0]

def find_near_mod(ocx,ll,mod):
    cx = int(ocx)
    ll = int(ll)
    mod = int(mod)
    if mod==0:
        return cx,ll
    si=1
    if ll<0:
        si=-1
    while 1:
        con=False
        for i in range(1,abs(ll)+1):
            if (cx+si*i)%mod==0:
                cx+=si*i
                ll -= si*i
                con = True
                break
        if not con:
            break
    return cx,ll

def do_step_jump(cpos,odx,ody,gg):
    isJ = False
    cx,cy = cpos
    dstx,odx = find_near_mod(cx,odx,gg)
    dsty,ody = find_near_mod(cy,ody,gg)
    if abs(odx)>=gg//2 and abs(ody)>=gg//2:
        dstx,odx = find_near_mod(dstx,odx,gg//2)
        dsty,ody = find_near_mod(dsty,ody,gg//2)
    dx = dstx-cx
    dy = dsty-cy
    if dx!=0 or dy!=0:
        isJ=True        
        mouse.Controller().move(dx,dy)
    return odx,ody,isJ

def conkey_decode(s):
    if '.' not in s:
        if len(s)<2:
            return '',0
        return s[0],int(s[1:])
    if s[:2]=='0.':
        r = s[2:]
        if not r:
            return '',0
        return '.',int(r)
    a,b = s.split('.')
    if not a or not b:
        return '',0
    return a+'.',int(b)

def do_conkey(a):
    if a=='4':
        return 'left'
    if a=='6':
        return 'right'
    if a=='8':
        return 'up'
    if a=='2':
        return 'down'
    if a=='5':
        return 'backspace'
    if a=='.':
        return 'delete'
    if a=='7':
        return -1,0
    if a=='3':
        return 0,-1
    if a=='9':
        return 0,1
    if a=='1':
        return 1,0
    return

def deal_conkey_inner(a,b,sl=True):
    if a in ('2','4','6','8','.','5'):        
        l = []        
        for i in range(b):
            l.append(do_conkey(a))        
        pyautogui.write(l)        
        if sl:
            time.sleep(0.02*b)        
    if a in ('1','3','7','9'):        
        dx,dy = do_conkey(a)
        m = mouse.Controller()
        for i in range(b):
            m.scroll(dx,dy)
            time.sleep(0.001)

def deal_conkey(s):
    sl = True
    a,b = conkey_decode(s)    
    print('conkey',a,b)
    gap = 10
    if len(a)==2 and a[0] in ('2','4','6','8','5') and a[1]=='.':
        a = a[0]        
        sl=False     
        gap = 100
    if a=='10.':        
        a = '.'
        sl=False     
        gap = 100
    while b>gap:
        if cfg.sum=='0':
            return
        b -= gap
        deal_conkey_inner(a,gap,sl)
        if cfg.sum=='0':
            return
        cfg.sum = str(b)
    deal_conkey_inner(a,b,sl)
    set_cfg_sum_0()

def clear_mouse_mode():
    cfg.mouse_mode = 0
    cfg.mouse_m_int_stop = (0,0)
    cfg.mouse_m_dst_stop = (0,0)
    cfg.mouse_m_left_start_time = 0
    cfg.mouse_m_left_dis = [0, 0]
    cfg.mouse_m_right_dis = [0, 0]
    cfg.mouse_m_left_fix_time = 0
    cfg.mouse_m_left_fix_pos = [0, 0]    
    cfg.mouse_m_left_max = [0, 0]

def set_cfg_sum_0():    
    #traceback.print_stack()      
    cfg.sum = '0'

def lock_step_clear():    
    cfg.lock_step = lock_step_default
    
def clear_lock():    
    cfg.lock = False
    lock_step_clear()
    cfg.lock_xing_mode = 0

def clear_add_show():
    cfg.add_show=[]
    cfg.capsShow =False

def set_to_chg():
    cfg.to_change_time = time.time()
    clear_add_show()

def clear_sca():    
    cfg.sca = 0
    cfg.sca_du = 0
    cfg.sca_cur = 0

def cut_to(d):    
    if d > max_l:
        d =  max_l
    if d < 0:
        d = 0
    return d

def set_to_abs_len(l):
    to_lock.acquire()    
    cfg.to = cut_to(l)
    set_cfg_sum_0()
    set_to_chg()
    if cfg.min_ge_force_show:
        cfg.min_ge = 0
    to_lock.release()
def switch_showcut():
    cfg.showCut = not cfg.showCut
    
def add_showmode():
    if cfg.show_mode==0:
        cfg.to_change_time = time.time()
    if not cfg.showCut:
        cfg.showCut = True
        cfg.show_mode = 1
        cfg.show_mode_plus = 0
        return     
    
    if cfg.show_mode==2:
        if cfg.show_mode_plus==0:
            cfg.show_mode_plus=1
            return
        cfg.showCut = False
        cfg.show_mode_plus = 0        
        return                
    
    cfg.show_mode += 1

def switch_left_middle_off():
    cfg.offMid = not cfg.offMid         
def switch_mouse_tip_l2():
    cfg.mouse_tip_no_show = not cfg.mouse_tip_no_show    
def switch_mouse_tip_l1():
    cfg.show_mouse_tip = not cfg.show_mouse_tip
def switch_show_zi_enable():
    cfg.always_show_one = not cfg.always_show_one
def switch_show_jiao():
    cfg.show_jiao = not cfg.show_jiao
def switch_show_pos():
    cfg.show_pos = not cfg.show_pos        
def minu_showmode():
    if not cfg.showCut:
        cfg.showCut=True
        return
    if cfg.show_mode_plus>0:
        cfg.show_mode_plus-=1
        return    
    if cfg.show_mode>0:
        cfg.show_mode -= 1        
        cfg.to_change_time = time.time()    

def switch_scroll():
    if cfg.scroll_one==0:
        cfg.scroll_one = 1
    elif cfg.scroll_one==1:
        cfg.scroll_one = 2
    else:
        cfg.scroll_one = 1      
def dotdot():    
    if cfg.isShow:
        cfg.isShow = False                
        cfg.show_one_on = False
        return
    
    if cfg.w2showing:        
        cfg.show_one_on = False
        return
    
    cfg.show_one_on = True
    cfg.show_one_onetime = True

def getp2(mouse_pos, doRound):
    if cfg.is_suo_middle:
        return cfg.suo_middle_pos
    if not is_sca():
        if mouse_pos:
            return mouse_pos
        return get_cur_pos()
    du, ll = getdu(mouse_pos)
    sx, sy = cfg.fix_pos
    if doRound:
        return round(ll * math.cos(du) + sx), round(ll * math.sin(du) + sy)
    else:
        return ll * math.cos(du) + sx, ll * math.sin(du) + sy
    
def getp(mouse_pos=None, doRound=False):
    x,y = getp2(mouse_pos,doRound)
    if doRound:
        return x,y
    if x==round(cfg.last_xy_float[0]) and y==round(cfg.last_xy_float[1]) :
        return cfg.last_xy_float
    return x,y    

def du_exit():
    pp = getp(None,True)
    con_set_pos(pp[0],pp[1])
    clear_sca()
    cfg.to_change_time = time.time()
    cfg.sca_noshow_last = False
    cfg.scroll_one=0
    
def update_du(add):        
    cfg.du_step = 0
    if add:
        cfg.scroll_one=1
    if not is_sca():
        cfg.sca_start_pos = get_cur_pos()
    du, ll = getdu()
    cfg.sca_du = du    
    if add:
        cfg.sca += 1
    if cfg.sca % len(sca_l)==0 and get_cur_pos()==cfg.sca_cur_pos:
        du_exit()
        return
    x, y = get_cur_pos()
    sx, sy = cfg.fix_pos
    dx = x - sx
    dy = y - sy
    cfg.sca_cur = math.atan2(dy, dx)
    cfg.sca_cur_pos = (x, y)    
    cfg.to_change_time = time.time()
    cfg.last_xy_float = getp()

def getdu0(mouse_pos):
    if mouse_pos:
        x,y = mouse_pos
    else:
        x, y = get_cur_pos()

    sx, sy = cfg.fix_pos
    dx = x - sx
    dy = y - sy
    du0 = math.atan2(dy, dx)
    return du0

def getdu(mouse_pos=None):
    x, y = get_cur_pos()
    if mouse_pos:
        x, y = mouse_pos
    sx, sy = cfg.fix_pos
    dx = x - sx
    dy = y - sy
    du0 = math.atan2(dy, dx)
    s = sca_l[cfg.sca%len(sca_l)]
    d =  du0 -cfg.sca_cur
    if d >  math.pi:
        d -= 2 * math.pi
    if d < - math.pi:
        d += 2 * math.pi
    du = cfg.sca_du + d * s
    if is_sca():        
        x, y = cfg.sca_start_pos
        dx = x - sx
        dy = y - sy
    ll = math.sqrt(dx*dx+dy*dy)
    return du, ll    

def is_sca_delay():    
    if time.time()-cfg.x2_mode_exit_time<x2_delay2 and abs(getdu0('')-cfg.sca_du)<0.01 and \
    get_cur_pos()==cfg.sca_cur_pos and cfg.sca==1:
        return False
    return cfg.sca != 0 or  cfg.sca_du != 0 or  cfg.sca_cur != 0  

def is_sca():        
    return cfg.sca != 0 or  cfg.sca_du != 0 or  cfg.sca_cur != 0  

#坐标绝对个数
def set_fix_ge_len(d):
    cfg.fix_scroll = d    
    cfg.min_ge = 0

#坐标个数相对变化
def deal_manu_scroll(d):    
    cfg.manu_add = d    
    if is_sca() and not cfg.has_show_sca:
        cfg.manu_add = d+1    

#坐标绝对像素长度
def set_scroll_len(d):
    set_to_abs_len(cfg.to+d)

def get_er_pos(b):    
    x, y = getp(None,False)        
    sx, sy = cfg.fix_pos
    dx = x - sx 
    dy = y - sy            
    if round(dx) == 0 and round(dy) == 0:
        return False,0,0         
    zx = round(dx * b + x)
    zy = round(dy * b + y)
    return True,zx,zy

def deal_add_er():
    if cfg.sum =='0.':
        cfg.capsShow = False
        set_cfg_sum_0()
        return
    f = int(float(cfg.sum))        
    if not cfg.capsShow and f not in cfg.add_show2:
        if not cfg.w2showing or f not in cfg.add_show:
            cfg.capsShow = True
            return
    cfg.capsShow =False
    if cfg.w2showing:
        if f in cfg.add_show2:
            cfg.add_show2.remove(f)
            if cfg.add_show[-1]==f:
                cfg.add_show = cfg.add_show[0:-1]
        else:
            cfg.add_show2.add(f)
        set_cfg_sum_0()
        return
    cfg.show_mode = 0
    set_fix_ge_len(f)
    dotdot()
    set_cfg_sum_0()

def deal_pressed():        
    from routin_x2 import exit_x2_mode
    if cfg.x2_mode:
        exit_x2_mode()
        return

    if cfg.sum !='0':
        if not cfg.w2showing and not cfg.capsShow:
            if cfg.sum[-1]!='.':
                cfg.conkey = cfg.sum                
                return
            cfg.sum = cfg.sum[:-1]            
        deal_add_er()        
        return
    
    if not cfg.is_pressed:
        cfg.press_job = time.time()        
        cfg.is_pressed = True
    else:
        cfg.press_job = -time.time()        
        cfg.is_pressed = False
    
def add_to_show_list(d,add):
    if not add:
        if len(cfg.add_show)>0 and cfg.add_show[-1]!=-1:
            cfg.add_show = cfg.add_show[:-1]
        return
    
    if len(cfg.add_show)==0:
        cfg.add_show.append(d)
        return
    
    if cfg.add_show[-1]==d:
        return
    
    if cfg.add_show[-1]==-1:
        cfg.add_show.append(d)
        return
    
    cfg.add_show[-1] = d

def deal_set(st, a):    
    if a < 0:
        return False
    
    if a==12:
        cfg.set_mode_min = not cfg.set_mode_min
        return True
    
    if a >= 0 and a <= 14:
        if cfg.set_mode_min:
            cfg.set_mode_min = False
            del_pos(a)
            return True
        
        add_p(a)
        return True 
    return False          

def cal_mouse_d(sp):
    pos = get_cur_pos()
    dx = pos[0] - sp[0]
    dy = pos[1] - sp[1]
    return math.sqrt(dx*dx+dy*dy)

def find_near_d(digit=False):
    st,en = cfg.snap[0],cfg.snap[-1]    
    st = int(st[0])
    en = int(en[0])
    f = cfg.x2_mode_d*(en-st)/100+st
    if digit:
        f = '%.2f' % f
    else:
        f = round(f)
    cfg.sum = str(f)

def deal_reset_one():
    if cfg.always_show_one:
        if cfg.reset_show_one:
            cfg.show_one_on = False
        else:
            cfg.show_one_on = True    

def move_p(a):    
    a = str(a)
    print('move', a, cfg.pos_m)
    if type(cfg.pos_m) ==type({}) and a in cfg.pos_m:
        clear(False, False)
        cfg.fix_pos =  cfg.pos_m[a]    
        con_set_pos(cfg.pos_m[a][0],cfg.pos_m[a][1])
        deal_reset_one()  

def load_pos():    
    try:
        f = open(pos_json_path)
        cfg.pos_m = json.load(f)
        f.close()        
    except:
        cfg.pos_m = {}

def save_pos():
    try:
        f = open(pos_json_path, 'w')
        json.dump(cfg.pos_m, f, indent=4)
        f.close()        
    except Exception as e:
        print(e)      

def del_pos(a):
    if str(a) in cfg.pos_m:
        del cfg.pos_m[str(a)]            
        save_pos()

def add_p(a):    
    a = str(a)
    load_pos()
    cfg.pos_m[a] = mouse.Controller().position
    print('pos', cfg.pos_m)
    save_pos()
    print('add', a)   

def get_screen_indx(x,y):
    for i in range(len(screen_config_for_indx)):
        con = screen_config_for_indx[i]
        if x>=con[0] and y>=con[1] and x<=con[2] and y<= con[3]:
            return i
    return min(len(screen_config_for_indx)-1, screen_idx_default)

def is_in_cur_screen(x, y):    
    i =  get_screen_indx(cfg.fix_pos[0], cfg.fix_pos[1])
    sx, sy, ex, ey =   screen_config[i]    
    if x >= sx and x <= ex and y >= sy and y <= ey:
        return True
    return False

def is_in_all_screen(x, y):
    for i in screen_config:
        sx, sy, ex, ey = i
        if x >= sx and x <= ex and y >= sy and y <= ey:
            return True
    return False
def is_in_screen(x, y):    
    for i in screen_config:
        sx, sy, ex, ey = i
        if x >= sx and x <= ex and y >= sy and y <= ey:
            return True
    return False

def move_and_set_fix(x,y):
    cfg.fix_pos =  (x, y)    
    s = cfg.sum
    clear(False)
    con_set_pos(x, y)    
    cfg.sum = s

def pause_xing():
    x, y = get_cur_pos()
    idx = get_screen_indx(x, y)
    idx += 1
    if idx >= len(screen_config_for_indx):
        idx = 0
    aa,b,c,d =  screen_config_for_indx[idx]        
    move_and_set_fix((aa+c) //2, (b+d) //2) 
   
def clear_mouse():
        cfg.left_mouse = []
        cfg.right_mouse = []        
if __name__ == '__main__':
    a = conkey_decode('110')
    print(a)
    